/**
 * Copyright (C) 2013-2014 the original author or authors.
 */
package com.foreveross.bsl.push.application.impl.channel;

import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.foreveross.bsl.push.application.impl.channel.ChannelSelector;
import com.foreveross.bsl.push.application.impl.channel.PushChannelable;
import com.foreveross.bsl.push.application.impl.channel.SendBag;
import com.foreveross.bsl.push.application.impl.channel.SendTarget;
import com.foreveross.bsl.push.application.impl.channel.SendTarget.TargetIdentity;
import com.foreveross.bsl.push.domain.entity.Push;
import com.foreveross.bsl.push.domain.entity.PushRequest;
import com.foreveross.bsl.push.domain.entity.PushTarget;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
 * xxx
 *
 * @author Wangyi
 * @version v1.0
 *
 * @date 2013-11-8
 *
 */
@Component
public class SendBagBuilder {

	@Autowired
	private ChannelSelector channelSelector;

	/**
	 * 构建channelId与SendTarget集合映射，根据push对象target属性中的token,deviceId,appId,channelId。
	 * 每个channelId对应一个SendTarget集体，每个SendTarget集合包含同一渠道下按appId区分的所有的发送目标，
	 * 每个SendTarget表示发送到同一appId下的所有目标，即token和deviceId
	 * @param pushs
	 * @return
	 */
	public List<SendBag> build(PushRequest pushRequest, List<Push> pushs) {
		final String sendBagNo = RandomStringUtils.randomAlphanumeric(10);
		Map<String, Set<SendTarget>> channelTargets = this.buildSendTargetMap(sendBagNo, pushs);
		List<SendBag> sendBags=Lists.newArrayList();
		for(String channelId : channelTargets.keySet()){
			PushChannelable channel = this.channelSelector.selectChannel(channelId);
			sendBags.add(new SendBag(channel, pushRequest, channelTargets.get(channelId), sendBagNo));
		}
		return sendBags;
	}

	public List<SendBag> build(Push push) {
		Validate.notNull(push, "push参数不能为空");
		Validate.notNull(push.getRequest(), "push.request属性不能为空");
		return build(push.getRequest(), Lists.newArrayList(push));
	}

	public Map<String, Set<SendTarget>> buildSendTargetMap(String sendBagNo, List<Push> pushs) {
		Map<String, SendTarget> appTargets=Maps.newHashMap();
		Map<String, Set<SendTarget>> channelTargets=Maps.newHashMap();
		for(Push p : pushs){
			p.setSendId(sendBagNo);
			PushTarget pt=p.getTarget();
			SendTarget st=appTargets.get(p.getChannelId()+"-"+pt.getAppId());
			if(st==null){
				st=new SendTarget();
				st.setAppId(pt.getAppId());
				st.setChannelId(p.getChannelId());
				appTargets.put(p.getChannelId()+"-"+pt.getAppId(), st);
			}
			st.getTargets().add(new TargetIdentity(pt.getToken(), pt.getDeviceId(), p.getId()));

			Set<SendTarget> sends=channelTargets.get(p.getChannelId());
			if(sends==null){
				sends=Sets.newHashSet();
				channelTargets.put(p.getChannelId(), sends);
			}
			sends.add(st);
		}
		return channelTargets;
	}
}
